﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace pyTivoMetadataManager
{
    public class RatingControl : Control
    {
        #region Properties
        private bool _hovering = false;
        private int _hoverGlyph;
        
        private int _selectedGlyph = 0;
        public int SelectedGlyph
        {
            get { return (_selectedGlyph); }
            set { 
                _selectedGlyph = value;
                Invalidate();
                OnSelectedItemChanged(new EventArgs());
            }
        }

        public int Value
        {
            get { return (SelectedGlyph); }
            set { SelectedGlyph = value; }
        }

        private int _leftMargin = 2;
        public int LeftMargin
        {
            get { return (_leftMargin); }
            set 
            {
                if (_leftMargin != value)
                {
                    _leftMargin = value;
                    Invalidate();
                }
            }
        }

        private int _rightMargin = 2;
        public int RightMargin
        {
            get { return (_rightMargin); }
            set
            {
                if (_rightMargin != value)
                {
                    _rightMargin = value;
                    Invalidate();
                }
            }
        }

        private int _topMargin = 2;
        public int TopMargin
        {
            get { return (_topMargin); }
            set
            {
                if (_topMargin!= value)
                {
                    _topMargin = value;
                    Invalidate();
                }
            }
        }

        private int _bottomMargin = 2;
        public int BottomMargin
        {
            get { return (_bottomMargin); }
            set
            {
                if (_bottomMargin != value)
                {
                    _bottomMargin = value;
                    Invalidate();
                }
            }
        }
        
        private int _glyphCount = 5;
        public int GlyphCount
        {
            get { return (_glyphCount); }
            set { _glyphCount = value; }
        }

        private int _glyphSpacing = 2;
        public int GlyphSpacing
        {
            get { return (_glyphSpacing); }
            set
            {
                if (_glyphSpacing != value)
                {
                    _glyphSpacing = value;
                    Invalidate();
                }
            }
        }

        private RatingGlyph _glyph = new StarRatingGlyph();
        public RatingGlyph Glyph
        {
            get { return (_glyph); }
            set
            {
                if (_glyph != value)
                {
                    _glyph = value;
                    Invalidate();
                }
            }
        }
        #endregion

        #region Events
        public event EventHandler SelectedItemChanged;
        protected virtual void OnSelectedItemChanged(EventArgs e)
        {
            if (SelectedItemChanged != null)
            {
                SelectedItemChanged(this, e);
            }
        }
        #endregion

        private Rectangle[] _glyphAreas;

        #region Constructors
        public RatingControl()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            DoubleBuffered = true;

            Width = 120;
            Height = 18;

            _glyphAreas = new Rectangle[GlyphCount];
        }
        #endregion

        #region Control Overrides
        protected override void OnPaint(PaintEventArgs pe)
        {
            pe.Graphics.Clear(BackColor);

            int glyphWidth = (Width - (LeftMargin + RightMargin + (GlyphSpacing * (GlyphCount - 1)))) / GlyphCount;
            int glyphHeight = Height - (TopMargin + BottomMargin);

            Rectangle drawArea = new Rectangle(LeftMargin, TopMargin, glyphWidth, glyphHeight);

            for (int i =0; i<GlyphCount; i++)
            {
                _glyphAreas[i].X = drawArea.X - GlyphSpacing / 2;
                _glyphAreas[i].Y = drawArea.Y;
                _glyphAreas[i].Width = drawArea.Width + GlyphSpacing / 2;
                _glyphAreas[i].Height = drawArea.Height;

                DrawGlyph(pe.Graphics, drawArea, i);

                drawArea.X += drawArea.Width + GlyphSpacing;
            }

            base.OnPaint(pe);
        }

        protected override void OnMouseEnter(System.EventArgs ea)
        {
            _hovering = true;
            Invalidate();
            base.OnMouseEnter(ea);
        }

        protected override void OnMouseLeave(System.EventArgs ea)
        {
            _hovering = false;
            Invalidate();
            base.OnMouseLeave(ea);
        }

        protected override void OnMouseMove(MouseEventArgs args)
        {
            for (int i = 0; i < GlyphCount; ++i)
            {
                if (_glyphAreas[i].Contains(args.X, args.Y))
                {
                    _hoverGlyph = i + 1;
                    Invalidate();
                    break;
                }
            }

            base.OnMouseMove(args);
        }

        protected override void OnClick(EventArgs e)
        {
            Point p = PointToClient(MousePosition);
            for (int i = 0; i < GlyphCount; ++i)
            {
                if (_glyphAreas[i].Contains(p.X, p.Y))
                {
                    _selectedGlyph = i + 1;
                    Invalidate();
                    break;
                }
            }

            base.OnClick(e);
        }
        #endregion

        #region Glyph Management
        private void DrawGlyph(Graphics g, Rectangle glyphArea, int glyphAreaIndex)
        {
            if (_hovering && _hoverGlyph > glyphAreaIndex)
            {
                Glyph.DrawHoverGlyph(g, glyphArea);
            }
            else if (_selectedGlyph > glyphAreaIndex)
            {
                Glyph.DrawSelectedGlyph(g, glyphArea);
            }
            else
            {
                Glyph.DrawEmptyGlyph(g, glyphArea);
            }
        }
        #endregion

    }
}
